package com.itcast.protocol;

import com.itcast.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;

@Slf4j
//@ChannelHandler.Sharable
public class MessageCodec extends ByteToMessageCodec<Message> {

    //编码，将message编码成ByteBuf
    @Override
    public void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
        // 4 个字节的魔数
        out.writeBytes(new byte[]{1, 2, 3, 4});
        //  1 个字节的版本,
        out.writeByte(1);
        // 1 个字节的序列化方式 jdk 0 , json 1
        out.writeByte(0);
        // 1 个字节的指令类型
        out.writeByte(msg.getMessageType());
        // 4 个字节的请求序号（int类型占用4个字节）
        out.writeInt(msg.getSequenceId());
        // 无意义，1个字节对齐填充（应为固定的长度是15=4+1+1+1+4+4，一般要是2的整数倍）
        out.writeByte(0xff);
        // 获取内容的字节数组，将message序列化成ByteBuf
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(msg);
        byte[] bytes = bos.toByteArray();
        // 内容长度，占4个字节
        out.writeInt(bytes.length);
        // 写入message序列化后的字节内容
        out.writeBytes(bytes);
    }

    //解码，将ByteBuf转换成Message
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        //魔数，读取4个字节
        int magicNum = in.readInt();
        //版本，读取1个字节
        byte version = in.readByte();
        //序列化类型，读取1个字节
        byte serializerType = in.readByte();
        //消息类型，读取1个字节
        byte messageType = in.readByte();
        //请求序号，读取4个字节
        int sequenceId = in.readInt();
        //读取1个字节无意义的对齐填充内容
        in.readByte();
        //内容长度，读取4个字节
        int length = in.readInt();
        byte[] bytes = new byte[length];
        //读取内容
        in.readBytes(bytes, 0, length);
        Message message=null;
        //jdk序列化
        if (messageType==0){
            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
            message = (Message) ois.readObject();
        }
        log.debug("{}, {}, {}, {}, {}, {}", magicNum, version, serializerType, messageType, sequenceId, length);
        log.debug("{}", message);
        //为了下个handler能获取到数据
        out.add(message);
    }
}